//单例模式
/*
概念：单例模式是一种常见的软件设计模式。它的核心结构只包含一个被称为单例的特殊类。它的目的是保证一个类仅有一个实例，并提供一个访问它的全局访问点，该实例被所有程序模块共享。

应用场景：有一些对象只需要一个，如：对话框、系统日志、显卡等设备的驱动程序对象、一台PC连接一个键盘。单例模式有3种实现方式：懒汉式、饿汉式和双重锁的形式。

懒汉：第一次用到类的实例的时候才回去实例化。

饿汉：单例类定义的时候就进行实例化。

*/

//懒汉式
//缺点：这个实现在单线程下是正确的，但在多线程情况下，如果两个线程同时首次调用GetInstance方法且同时检测到Instance是NULL，则两个线程会同时构造一个实例给Instance，这样就会发生错误。
class singleton   //实现单例模式的类  
{  
private:  
    singleton(){}  //私有的构造函数  
    static singleton* Instance;  
public:  
    static singleton* GetInstance()  
    {  
        if (Instance == NULL) //判断是否第一调用  
            Instance = new singleton();  
        return Instance;  
    }  
}; 


//改进的懒汉式（双重检查锁）
//思路：只有在第一次创建的时候进行加锁，当Instance不为空的时候就不需要进行加锁的操作。代码如下：
class singleton   //实现单例模式的类  
{  
private:  
    singleton(){}  //私有的构造函数  
    static singleton* Instance;  
    
public:  
    static singleton* GetInstance()  
    {  
        if (Instance == NULL) //判断是否第一调用  
        {   
            Lock(); //表示上锁的函数  
            if (Instance == NULL)  
            {  
                Instance = new singleton();  
            }  
            UnLock() //解锁函数  
        }             
        return Instance;  
    }  
};



//饿汉式
//饿汉式的特点是一开始就加载了，如果说懒汉式是“时间换空间”，那么饿汉式就是“空间换时间”，因为一开始就创建了实例，所以每次用到的之后直接返回就好了。饿汉模式是线程安全的。

//头文件
// 饿汉实现 /

class Singleton
{
public:
    // 获取单实例
    static Singleton* GetInstance();

    // 释放单实例，进程退出时调用
    static void deleteInstance();
    
    // 打印实例地址
    void Print();

private:
    // 将其构造和析构成为私有的, 禁止外部构造和析构
    Singleton();
    ~Singleton();

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    Singleton(const Singleton &signal);
    const Singleton &operator=(const Singleton &signal);

private:
    // 唯一单实例对象指针
    static Singleton *g_pSingleton;
};

//源文件
// 代码一运行就初始化创建实例 ，本身就线程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton();

Singleton* Singleton::GetInstance()
{
    return g_pSingleton;
}

void Singleton::deleteInstance()
{
    if (g_pSingleton)
    {
        delete g_pSingleton;
        g_pSingleton = nullptr;
    }
}

void Singleton::Print()
{
    std::cout << "我的实例内存地址是:" << this << std::endl;
}

Singleton::Singleton()
{
    std::cout << "构造函数" << std::endl;
}

Singleton::~Singleton()
{
    std::cout << "析构函数" << std::endl;
}





//懒汉模式完整代码示例
#include<iostream>
using namespace std;
class CSingleton
{
public:
	static CSingleton* getInstance()
	{
		if (m_MyInstancePtr == nullptr)
			m_MyInstancePtr = new CSingleton();
		return m_MyInstancePtr;
	}
private:
	CSingleton(){ }
	~CSingleton()
	{
		if (m_MyInstancePtr != nullptr)
		{
			delete m_MyInstancePtr;
			m_MyInstancePtr = nullptr;
		}
	}
	static CSingleton* m_MyInstancePtr;
};
CSingleton* CSingleton::m_MyInstancePtr = nullptr;

int main()
{
	CSingleton* instance1 = CSingleton::getInstance();
	CSingleton* instance2 = CSingleton::getInstance();
	cout << instance1 << '\t' << instance2 << endl;
	if (instance1 == instance2)
		cout << "单例创建成功" << endl;
	return 0;
}

